using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MinimalistFoodStreet.BackEnd.Infrastructure.Attributes;
using MinimalistFoodStreet.BackEnd.Infrastructure.Dtos.Request.Tables;
using MinimalistFoodStreet.BackEnd.Infrastructure.Dtos.Response;
using MinimalistFoodStreet.BackEnd.Infrastructure.Dtos.Response.Tables;
using MinimalistFoodStreet.BackEnd.Infrastructure.EFCore;
using MinimalistFoodStreet.BackEnd.Server.TableEFCore;
using MinimalistFoodStreet.BackEnd.Server.Server.RequestExtend.Tables;
using MinimalistFoodStreet.BackEnd.Server.Server.ResponseExtend.Tables;
using MinimalistFoodStreet.BackEnd.Server.IServer.Tables;
using MinimalistFoodStreet.BackEnd.Infrastructure.Tools;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using System.Runtime.Versioning;
using System.Security.Principal;
using Microsoft.Extensions.Options;

namespace MinimalistFoodStreet.BackEnd.Server.Server.Tables
{
    [InjectClass]
    public class SuppliersServer : ISuppliersServer
    {
        private readonly ServerRepository _serverRepository;
        private readonly IConfiguration _configuration;

        public SuppliersServer(DbContext dbContext, IConfiguration configuration)
        {
            _serverRepository = new ServerRepository(dbContext);
            _configuration = configuration;
        }

        public async Task<ResponseApiDto> AddAsync(RequestCreateSuppliersDto dto)
        {
            if(await _serverRepository.suppliersEFCore.Query(d => d.SShopName == dto.shopName).AnyAsync())
            {
                return ResponseApiDto.Fail("店铺名称已被使用");
            }
            if (await _serverRepository.accountsEFCore.Query(d => d.APhone == dto.phone).AnyAsync())
            {
                return ResponseApiDto.Fail("电话号码已被使用");
            }
            if (dto.password.Length < 6)
            {
                return ResponseApiDto.Fail("密码不能低于6位");
            }
            if (dto.photo.Count > 20)
            {
                return ResponseApiDto.Fail("最多上传20张企业图片");
            }
            if (dto.qualification.Count > 20)
            {
                return ResponseApiDto.Fail("最多上传20张资质图片");
            }
            int affectedRows = 0;
            List<string> tempImagePaths = new List<string>();
            string imagePath = "";
            await _serverRepository.ExecuteInTransactionAsync(async () =>
            {
                // 生成账号
                string salt = Tools.Guid_1();
                Account account = new Account
                {
                    AAccount = dto.phone,
                    APhone = dto.phone,
                    APassword = Encrypt.GetMd5Hash(dto.password + salt),
                    ASalt = salt,
                    AEndpoint = "suppliers"
                };
                affectedRows += await _serverRepository.accountsEFCore.AddAsync(account);
                // 添加供应商
                Supplier supplier = dto.ToCreateEntity();
                supplier.SAccountId = account.AId;
                affectedRows += await _serverRepository.suppliersEFCore.AddAsync(supplier);
                // 上传图片
                supplier.SPhoto = "";
                imagePath = Path.Combine(_configuration["ImageBasePath"], "Supplier", supplier.SId.ToString());
                for (int i = 0; i < dto.photo.Count; i++)
                {
                    IFormFile photo = dto.photo[i];
                    string imageName = await Upload.UploadImageAsync(photo, imagePath, true);
                    if (supplier.SPhoto != "") supplier.SPhoto += ",";
                    supplier.SPhoto += imageName;
                    tempImagePaths.Add(Path.Combine(imagePath, imageName));
                }
                supplier.SQualification = "";
                for (int i = 0; i < dto.qualification.Count; i++)
                {
                    IFormFile photo = dto.qualification[i];
                    string imageName = await Upload.UploadImageAsync(photo, imagePath, true);
                    if (supplier.SQualification != "") supplier.SQualification += ",";
                    supplier.SQualification += imageName;
                    tempImagePaths.Add(Path.Combine(imagePath, imageName));
                }
                string imageName2 = await Upload.UploadImageAsync(dto.logo, imagePath, true);
                supplier.SLogo = imageName2;
                tempImagePaths.Add(Path.Combine(imagePath, imageName2));
                affectedRows += await _serverRepository.suppliersEFCore.UpdateAsync(supplier);
            }, () =>
            {
                // 清理图片
                for (int i = 0; i < tempImagePaths.Count; i++)
                {
                    string tempImagePath = tempImagePaths[i];
                    if (File.Exists(tempImagePath))
                    {
                        File.Delete(tempImagePath);
                    }
                }
                // 删除文件夹
                if (Directory.Exists(imagePath))
                {
                    Directory.Delete(imagePath, true);
                }
                affectedRows = 0;
                return null;
            });
            return ResponseApiDto.Create(affectedRows);
        }


        public async Task<ResponseApiDto> UpdateAsync(RequestUpdateSuppliersDto dto)
        {
            if (await _serverRepository.suppliersEFCore.Query(d => d.SShopName == dto.shopName&&d.SId!=dto.id).AnyAsync())
            {
                return ResponseApiDto.Fail("店铺名称已被使用");
            }
            Supplier supplier = await _serverRepository.suppliersEFCore.Query(d => d.SId == dto.id).SingleOrDefaultAsync();
            if (supplier == null)
            {
                return ResponseApiDto.Fail("该实例不存在");
            }
            if ((dto.retainPhoto?.Count ?? 0) + (dto.photo?.Count ?? 0) > 20)
            {
                return ResponseApiDto.Fail("最多上传20张企业图片");
            }
            if ((dto.retainQualification?.Count ?? 0) + (dto.qualification?.Count ?? 0) > 20)
            {
                return ResponseApiDto.Fail("最多上传20张资质图片");
            }
            supplier.SOpenId = dto.openId;
            supplier.SAddress = dto.address;
            supplier.SShopName = dto.shopName;
            supplier.SAnnouncement = dto.announcement;
            supplier.SType = dto.type;
            supplier.SEnterpriseName = dto.enterpriseName;
            int affectedRows = 0;
            string imagePath = Path.Combine(_configuration["ImageBasePath"], "Supplier", supplier.SId.ToString());
            List<FileInfo> tempDeletedImages = new List<FileInfo>();
            List<string> tempImagePaths = new List<string>();
            await _serverRepository.ExecuteInTransactionAsync(async () =>
            {
                // 删除图片
                List<string> photoNames = supplier.SPhoto.Split(",").ToList();
                supplier.SPhoto = "";
                for (int i = 0; i < photoNames.Count; i++)
                {
                    string photoName = photoNames[i];
                    if (dto.retainPhoto == null || !dto.retainPhoto.Contains(photoName))
                    {
                        if (File.Exists(Path.Combine(imagePath, photoName)))
                        {
                            tempDeletedImages.Add(new FileInfo(Path.Combine(imagePath, photoName)));
                            File.Delete(Path.Combine(imagePath, photoName));
                        }
                    }
                    else
                    {
                        if (supplier.SPhoto != "") supplier.SPhoto += ",";
                        supplier.SPhoto += photoName;
                    }
                }
                List<string> qualificationNames = supplier.SQualification.Split(",").ToList();
                supplier.SQualification = "";
                for (int i = 0; i < qualificationNames.Count; i++)
                {
                    string qualificationName = qualificationNames[i];
                    if (dto.retainQualification == null || !dto.retainQualification.Contains(qualificationName))
                    {
                        if (File.Exists(Path.Combine(imagePath, qualificationName)))
                        {
                            tempDeletedImages.Add(new FileInfo(Path.Combine(imagePath, qualificationName)));
                            File.Delete(Path.Combine(imagePath, qualificationName));
                        }
                    }
                    else
                    {
                        if (supplier.SQualification != "") supplier.SQualification += ",";
                        supplier.SQualification += qualificationName;
                    }
                }
                if (dto.logo != null)
                {
                    if (File.Exists(Path.Combine(imagePath, supplier.SLogo)))
                    {
                        tempDeletedImages.Add(new FileInfo(Path.Combine(imagePath, supplier.SLogo)));
                        File.Delete(Path.Combine(imagePath, supplier.SLogo));
                    }
                }
                // 添加图片
                if (dto.photo != null)
                {
                    for (int i = 0; i < dto.photo.Count; i++)
                    {
                        IFormFile photo = dto.photo[i];
                        string imageName = await Upload.UploadImageAsync(photo, imagePath, true);
                        if (supplier.SPhoto != "") supplier.SPhoto += ",";
                        supplier.SPhoto += imageName;
                        tempImagePaths.Add(Path.Combine(imagePath, imageName));
                    }
                }
                if (dto.qualification != null)
                {
                    for (int i = 0; i < dto.qualification.Count; i++)
                    {
                        IFormFile qualification = dto.qualification[i];
                        string imageName = await Upload.UploadImageAsync(qualification, imagePath,true);
                        if (supplier.SQualification != "") supplier.SQualification += ",";
                        supplier.SQualification += imageName;
                        tempImagePaths.Add(Path.Combine(imagePath, imageName));
                    }
                }
                if (dto.logo != null)
                {
                    string imageName2 = await Upload.UploadImageAsync(dto.logo, imagePath, true);
                    supplier.SLogo = imageName2;
                    tempImagePaths.Add(Path.Combine(imagePath, imageName2));
                }
                affectedRows += await _serverRepository.suppliersEFCore.UpdateAsync(supplier);
                Account account = await _serverRepository.accountsEFCore.Query(d => d.AId == supplier.SAccountId).SingleAsync();
                account.AAccount = dto.phone;
                account.APhone = dto.phone;
                // 重置密码
                if (dto.passwordReset != null)
                {
                    account.ASalt = Tools.Guid_1();
                    account.APassword = Encrypt.GetMd5Hash(dto.passwordReset + account.ASalt);
                }
                affectedRows += await _serverRepository.accountsEFCore.UpdateAsync(account);
            }, () =>
            {
                // 删除图片
                foreach (var imagePath in tempImagePaths)
                {
                    if (File.Exists(imagePath))
                        File.Delete(imagePath);
                }
                // 恢复图片
                foreach (var deletedImage in tempDeletedImages)
                {
                    deletedImage.CopyTo(Path.Combine(imagePath, deletedImage.Name), overwrite: true);
                }
                affectedRows = 0;
                return null;
            });
            return ResponseApiDto.Create(affectedRows);
        }

        public async Task<ResponseApiDto> DeleteAsync(RequestDeleteSuppliersDto dto)
        {
            if (!await _serverRepository.suppliersEFCore.Query(d => d.SId == dto.id).AnyAsync())
            {
                return ResponseApiDto.Fail("该供应商不存在");
            }
            Supplier supplier = await _serverRepository.suppliersEFCore.Query(d => d.SId == dto.id).SingleAsync();
            int affectedRows = 0;
            string imagePath = Path.Combine(_configuration["ImageBasePath"], "Supplier", supplier.SId.ToString());
            List<FileInfo> tempDeletedImages = new List<FileInfo>();
            await _serverRepository.ExecuteInTransactionAsync(async () =>
            {
                // 删除供应商
                affectedRows += await _serverRepository.suppliersEFCore.Query(d => d.SId == dto.id).ExecuteDeleteAsync();
                // 删除账号
                affectedRows += await _serverRepository.accountsEFCore.Query(d => d.AId == supplier.SAccountId).ExecuteDeleteAsync();
                // 删除图片
                List<string> photoNames = supplier.SPhoto.Split(",").ToList();
                for (int i = 0; i < photoNames.Count; i++)
                {
                    string photoName = photoNames[i];
                    if (File.Exists(Path.Combine(imagePath, photoName)))
                    {
                        tempDeletedImages.Add(new FileInfo(Path.Combine(imagePath, photoName)));
                        File.Delete(Path.Combine(imagePath, photoName));
                    }
                }
                List<string> qualificationNames = supplier.SQualification.Split(",").ToList();
                for (int i = 0; i < qualificationNames.Count; i++)
                {
                    string qualificationName = qualificationNames[i];
                    if (File.Exists(Path.Combine(imagePath, qualificationName)))
                    {
                        tempDeletedImages.Add(new FileInfo(Path.Combine(imagePath, qualificationName)));
                        File.Delete(Path.Combine(imagePath, qualificationName));
                    }
                }
                if (File.Exists(Path.Combine(imagePath, supplier.SLogo)))
                {
                    tempDeletedImages.Add(new FileInfo(Path.Combine(imagePath, supplier.SLogo)));
                    File.Delete(Path.Combine(imagePath, supplier.SLogo));
                }
                //删除文件夹
                if (Directory.Exists(imagePath))
                {
                    Directory.Delete(imagePath);
                }
            }, () =>
            {
                // 恢复文件夹
                if (!Directory.Exists(imagePath))
                {
                    Directory.CreateDirectory(imagePath);
                }
                // 恢复图片
                foreach (var deletedImage in tempDeletedImages)
                {
                    deletedImage.CopyTo(Path.Combine(imagePath, deletedImage.Name), overwrite: true);
                }
                affectedRows = 0;
                return null;
            });
            return ResponseApiDto.Create(affectedRows);
        }

        public async Task<ResponseApiDto> DetailAsync(int id)
        {
            Supplier supplier = await _serverRepository.suppliersEFCore.Query(d => d.SId == id).SingleOrDefaultAsync();
            if (supplier == null)
            {
                return ResponseApiDto.Fail("该实例不存在");
            }
            Account account = await _serverRepository.accountsEFCore.Query(d => d.AId == supplier.SAccountId).SingleAsync();
            var responseDto = supplier.ToResponseDto(account);
            responseDto.typeName = await _serverRepository.dictionarysEFCore.Query(d => d.DId == responseDto.type).Select(d => d.DValue).SingleOrDefaultAsync();
            return ResponseApiDto.Ok("数据已获取", responseDto);
        }

        public async Task<ResponseApiDto> PaginationAsync(int page, int limit, string? key)
        {
            int total = 0;
            List<Supplier> suppliers = await _serverRepository.suppliersEFCore.Pagination(d => key == null || d.SEnterpriseName.Contains(key) || ((d.SAccount == null || d.SAccount.AAccount == null) ? false : d.SAccount.AAccount.Contains(key)), false, d => d.SId, out total, page, limit).ToListAsync();
            List<ResponseSuppliersDto> responseSuppliersDtos = new List<ResponseSuppliersDto>();
            for (int i = 0; i < suppliers.Count; i++)
            {
                Supplier supplier = suppliers[i];
                var responseDto = supplier.ToResponseDto(await _serverRepository.accountsEFCore.Query(e => e.AId == supplier.SAccountId).SingleAsync());
                responseDto.typeName = await _serverRepository.dictionarysEFCore.Query(d => d.DId == responseDto.type).Select(d => d.DValue).SingleOrDefaultAsync();
                responseSuppliersDtos.Add(responseDto);
            }
            return ResponseApiDto.Ok("数据已获取", new { data = responseSuppliersDtos, total = total });
        }

        public async Task<ResponseApiDto> GetOptionByShopName(string shopName)
        {
            if (string.IsNullOrEmpty(shopName))
            {
                return ResponseApiDto.Fail("店铺名称不能为空");
            }
            var options = await _serverRepository.suppliersEFCore.Query(d => d.SShopName.Contains(shopName)).Select(d=>new {value=d.SShopName}).ToListAsync();
            return ResponseApiDto.Ok("数据已获取",options);
        }
    }
}